home *** CD-ROM | disk | FTP | other *** search
- /** 3DGPL *************************************************\
- * (8bit deep bitmap) *
- * 2D graphics and 2D clipping extentions for shaded *
- * and textured polygons (has to be linked with regular *
- * routines). *
- * *
- * Defines: *
- * G_ambient_polygon regular polygon; *
- * G_shaded_polygon shaded polygon; *
- * G_textured_polygon textured polygon. *
- * *
- * Internals: *
- * GI_scan scanning an edge; *
- * GI_boarder_array_init init left/right boundaries. *
- * *
- * (6/1995) By Sergei Savchenko. (savs@cs.mcgill.ca). *
- * Copyright (c) 1995 Sergei Savchenko. *
- * THIS SOURCE CODE CAN'T BE USED FOR COMERCIAL PURPOSES *
- * WITHOUT AUTHORISATION *
- \**********************************************************/
-
- #include <limits.h> /* INT_MAX/INT_MIN */
-
- #ifdef __MWERKS__
- #include "hardware.h" /* hardware specific stuff */
- #include "clipper.h" /* 2D clipping */
- #include "graphics.h" /* 2D macros */
- #include "trans.h" /* T_LOG_FOCUS */
- #else
- #include "../hardware/hardware.h" /* hardware specific stuff */
- #include "../clipper/clipper.h" /* 2D clipping */
- #include "../graphics/graphics.h" /* 2D macros */
- #include "../trans/trans.h" /* T_LOG_FOCUS */
- #endif
-
- extern unsigned char *G_buffer; /* the bitmap's bits */
-
- int G_start[HW_SCREEN_Y_SIZE]; /* polygon's */
- int G_end[HW_SCREEN_Y_SIZE]; /* horizontal boundaries */
- int G_miny,G_maxy; /* vertical boundaries */
-
- #define G_P 10 /* fixed point math prcision */
- #define G_LINEAR 32 /* linearely interpolate for */
-
- signed_32_bit G_0_start[HW_SCREEN_Y_SIZE]; /* contains [32-G_P].[G_P] values */
- signed_32_bit G_0_end[HW_SCREEN_Y_SIZE]; /* this thingie is to work faster */
- signed_32_bit G_1_start[HW_SCREEN_Y_SIZE]; /* then multidimensional array */
- signed_32_bit G_1_end[HW_SCREEN_Y_SIZE]; /* hope so, */
- signed_32_bit G_2_start[HW_SCREEN_Y_SIZE];
- signed_32_bit G_2_end[HW_SCREEN_Y_SIZE];
-
- signed_32_bit *G_rest_start[C_MAX_DIMENSIONS]={G_0_start,G_1_start,G_2_start};
- signed_32_bit *G_rest_end[C_MAX_DIMENSIONS]={G_0_end,G_1_end,G_2_end};
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * INTERNAL: Scan converting a N dimensional line. *
- * --------- *
- \* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
- void GI_scan(int *edges,int dimension,int skip)
- {
- signed_32_bit cur_v[C_MAX_DIMENSIONS]; /* initial values for Z+ dims */
- signed_32_bit inc_v[C_MAX_DIMENSIONS]; /* increment for Z+ dimensions */
- signed_32_bit tmp;
- int dx,dy,long_d,short_d;
- register int d,add_dh,add_dl;
- register int inc_xh,inc_yh,inc_xl,inc_yl;
- int x,y,i,j;
- int *v1,*v2; /* first and second vertices */
-
- v1=edges; edges+=skip; v2=edges; /* length ints in each */
-
- if(C_line_y_clipping(&v1,&v2,dimension)) /* vertical clipping */
- {
- dx=*v2++; dy=*v2++; /* extracting 2-D coordinates */
- x=*v1++; y=*v1++; /* v2/v1 point remaining dim-2 */
- dimension-=2;
-
- if(y<G_miny) G_miny=y;
- if(y>G_maxy) G_maxy=y;
- if(dy<G_miny) G_miny=dy;
- if(dy>G_maxy) G_maxy=dy; /* updating vertical size */
-
- dx-=x; dy-=y; /* ranges */
-
- if(dx<0){dx=-dx; inc_xh=-1; inc_xl=-1;} /* making sure dx and dy >0 */
- else { inc_xh=1; inc_xl=1; } /* adjusting increments */
- if(dy<0){dy=-dy; inc_yh=-1; inc_yl=-1;}
- else { inc_yh=1; inc_yl=1; }
-
- if(dx>dy){long_d=dx;short_d=dy;inc_yl=0;} /* long range,&making sure either */
- else {long_d=dy;short_d=dx;inc_xl=0;} /* x or y is changed in L case */
-
- d=2*short_d-long_d; /* initial value of d */
- add_dl=2*short_d; /* d adjustment for H case */
- add_dh=2*short_d-2*long_d; /* d adjustment for L case */
-
- for(i=0;i<dimension;i++) /* for all remaining dimensions */
- {
- tmp=v1[i]; tmp<<=G_P; cur_v[i]=tmp; /* f.p. start value */
- tmp=v2[i]-v1[i]; tmp<<=G_P; /* f.p. increment */
- if(long_d>0) inc_v[i]=tmp/long_d; /* if needed (non 0 lines) */
- }
-
- for(i=0;i<=long_d;i++) /* for all points in longer range */
- {
- if(x<G_start[y]) /* further then rightmost */
- {
- G_start[y]=x; /* the begining of scan line */
- for(j=0;j<dimension;j++)
- G_rest_start[j][y]=cur_v[j]; /* all other dimensions */
- }
-
- if(G_end[y]<x) /* further the leftmost */
- {
- G_end[y]=x; /* the end of scan line */
- for(j=0;j<dimension;j++)
- G_rest_end[j][y]=cur_v[j]; /* and for other dimension */
- }
-
- if(d>=0){x+=inc_xh;y+=inc_yh;d+=add_dh;} /* previous point was H type */
- else {x+=inc_xl;y+=inc_yl;d+=add_dl;} /* previous point was L type */
- for(j=0;j<dimension;j++)
- cur_v[j]+=inc_v[j]; /* for all other dimensions */
- }
- }
- }
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * INTERNAL: Initialization of polygon boundaries. *
- * --------- *
- \* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
- void GI_boarder_array_init(void)
- {
- G_miny=INT_MAX; /* polygon starts here */
- G_maxy=INT_MIN; /* polygon ends here */
-
- HW_set_int(G_start,HW_SCREEN_Y_SIZE,INT_MAX);
- HW_set_int(G_end,HW_SCREEN_Y_SIZE,INT_MIN);/* limiting values */
- }
-
- /**********************************************************\
- * Rendering a polygon. *
- * Accepts 2-tuples (X,Y) per vertex. *
- \**********************************************************/
-
- void G_ambient_polygon(int *edges,int length,unsigned char colour)
- {
- int new_edges[G_MAX_TUPLES]; /* verticaly clipped polygon */
- int new_length; /* although no edges there yet */
- register unsigned char *l_adr,*adr;
- register int beg,end,i;
-
- GI_boarder_array_init(); /* initializing the arrays */
-
- new_length=C_polygon_x_clipping(edges,new_edges,2,length);
-
- for(i=0;i<new_length;i++)
- GI_scan(&new_edges[i*2],2,2); /* Searching polygon boarders */
-
- if(G_miny<=G_maxy) /* nothing to do? */
- {
- l_adr=G_buffer+G_miny*HW_SCREEN_X_SIZE; /* addr of 1st byte of 1st line */
-
- for(; G_miny<=G_maxy; G_miny++,
- l_adr+=HW_SCREEN_X_SIZE) /* rendering all lines */
- {
- adr=l_adr+(beg=G_start[G_miny]); /* addr of the current line */
- end=G_end[G_miny]-beg+1; /* ends here */
-
- HW_set_char((char*)adr,end,colour); /* rendering single line */
- }
- }
- }
-
- /**********************************************************\
- * Rendering an Interpolatively shaded polygon. *
- * Accepts 3-tuples (X,Y,ColourIntensity) per vertex. *
- \**********************************************************/
-
- void G_shaded_polygon(int *edges,int length)
- {
- int new_edges[G_MAX_SHADED_TUPLES]; /* verticaly clipped polygon */
- int new_length;
- register unsigned char *l_adr,*adr;
- register int beg,end,i;
- register signed_32_bit cur_c,inc_c; /* current colour and it's inc */
-
- GI_boarder_array_init(); /* initializing the array */
-
- new_length=C_polygon_x_clipping(edges,new_edges,3,length);
-
- for(i=0;i<new_length;i++)
- GI_scan(&new_edges[i*3],3,3); /* Searching polygon boarders */
-
- if(G_miny<=G_maxy) /* nothing to do? */
- {
- l_adr=G_buffer+G_miny*HW_SCREEN_X_SIZE; /* addr of 1st byte of 1st line */
-
- for(; G_miny<=G_maxy; G_miny++,
- l_adr+=HW_SCREEN_X_SIZE) /* rendering all lines */
- {
- adr=l_adr+(beg=G_start[G_miny]); /* addr of the current line */
- end=G_end[G_miny]; /* ends here */
-
- cur_c=G_0_start[G_miny]; /* colour starts with this value */
- inc_c=G_0_end[G_miny]-cur_c;
- if(end>beg) inc_c/=end-beg+1; /* f.p. increment */
-
- for(;beg<=end;beg++) /* render this lines */
- {
- *adr++=cur_c>>G_P; /* rendering single point */
- cur_c+=inc_c; /* incrementing colour */
- }
- }
- }
- }
-
- /**********************************************************\
- * Rendering a texture rendered polygon. *
- * Accepts 4-tuples - (X,Y,TextureX,TextureY) per vertex.*
- * The applied texture is a 8bit deep square bitmap with:*
- * *
- * log_texture_size=log texture_size *
- * 2 *
- \**********************************************************/
-
- void G_textured_polygon(int *edges,int length,int *O,int *u,int *v,
- unsigned char *texture,int log_texture_size,
- int log_texture_scale
- )
- {
- int new_edges[G_MAX_SHADED_TUPLES]; /* verticaly clipped polygon */
- int new_length;
- signed_32_bit Vx,Vy,Vz;
- signed_32_bit Ux,Uy,Uz; /* extracting vectors */
- signed_32_bit x0,y0,z0;
- signed_32_bit ui,uj,uc;
- signed_32_bit vi,vj,vc;
- signed_32_bit zi,zj,zc; /* back to texture coeficients */
- signed_32_bit v0,u0;
- signed_32_bit xx,yy,zz,zzz;
- int xstart,xend;
- signed_32_bit txstart,tystart;
- signed_32_bit txend,tyend;
- signed_32_bit txinc,tyinc;
- register unsigned char *g_adr,*adr;
- register int i,x,y;
- signed_32_bit txtrmasc=(0x1<<(log_texture_size+G_P))-0x1;
- log_texture_scale+=G_P;
-
- GI_boarder_array_init(); /* initializing the array */
-
- new_length=C_polygon_x_clipping(edges,new_edges,4,length);
-
- for(i=0;i<new_length;i++)
- GI_scan(&new_edges[i*4],2,4); /* Searching polygon boarders */
-
- if(G_miny<=G_maxy) /* nothing to do? */
- {
- x0=O[0]; y0=O[1]; z0=O[2];
- u0=O[3]<<G_P; v0=O[4]<<G_P; /* world point <-> texture point */
-
- Vx=v[0]; Vy=v[1]; Vz=v[2];
- Ux=u[0]; Uy=u[1]; Uz=u[2]; /* extracting vectors */
-
- ui=(Vz*y0)-(Vy*z0);
- uj=(Vx*z0)-(Vz*x0);
- uc=(Vy*x0)-(Vx*y0);
- vi=(Uy*z0)-(Uz*y0);
- vj=(Uz*x0)-(Ux*z0);
- vc=(Ux*y0)-(Uy*x0);
- zi=(Vy*Uz)-(Vz*Uy);
- zj=(Vz*Ux)-(Vx*Uz);
- zc=(Vx*Uy)-(Vy*Ux); /* back to texture */
-
- g_adr=G_buffer+G_miny*HW_SCREEN_X_SIZE; /* addr of 1st byte of 1st line */
-
- for(; G_miny<=G_maxy; G_miny++,
- g_adr+=HW_SCREEN_X_SIZE) /* rendering all lines */
- {
- xstart=G_start[G_miny];
- adr=g_adr+xstart;
- xstart-=HW_SCREEN_X_CENTRE;
- x=xstart;
- xend=G_end[G_miny]-HW_SCREEN_X_CENTRE;
- y=G_miny-HW_SCREEN_Y_CENTRE;
-
- xx=((y*uj)>>T_LOG_FOCUS)+uc;
- yy=((y*vj)>>T_LOG_FOCUS)+vc;
- zz=((y*zj)>>T_LOG_FOCUS)+zc; /* valid for the hole run */
-
- if(( zzz=zz+((x*zi)>>T_LOG_FOCUS) )!=0)
- {
- txend=( (xx+ ((x*ui)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +u0;
- tyend=( (yy+ ((x*vi)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +v0;
- }
-
- for(;xstart<xend;)
- {
- x+=G_LINEAR; if(x>xend) x=xend; /* size of linear run */
- txstart=txend;
- tystart=tyend;
-
- if(( zzz=zz+((x*zi)>>T_LOG_FOCUS) )!=0)
- {
- txend=( (xx+ ((x*ui)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +u0;
- tyend=( (yy+ ((x*vi)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +v0;
- }
-
- length=x-xstart; /* ends here */
- if(length!=0) { txinc=(txend-txstart)/length;
- tyinc=(tyend-tystart)/length;
- }
-
- for(;xstart<x;xstart++) /* linear run */
- {
- txstart&=txtrmasc; tystart&=txtrmasc; /* wrap around */
- *adr++=*(texture+((tystart>>G_P)<<log_texture_size)+(txstart>>G_P));
- txstart+=txinc; tystart+=tyinc; /* new position in the texture */
- }
- }
- }
- }
- }
-
- /**********************************************************/
-